#    Tichy
#
#    copyright 2008 Guillaume Chereau (charlie137@gmail.com)
#
#    This file is part of Tichy.
#
#    Tichy is free software: you can redistribute it and/or modify it
#    under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    Tichy is distributed in the hope that it will be useful, but
#    WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#    General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Tichy.  If not, see <http://www.gnu.org/licenses/>.

from geo import Vect


# XXX: This is too slow ! We can optimize a lot if we assume that the font is
#      always monospace (and we could use textwrap module as well, so we
#      should do it I think.)


class DummyPainter(object):

    def move(self, pos):
        pass

    def umove(self, pos):
        pass

    def draw_text(self, text, font, color):
        return Vect(font.size(text)[0], 0)

    def fill(color, size):
        pass


class Element(object):

    def draw(self, painter, font, color, width):
        pass


class List(list, Element):

    def __init__(self, elements=[]):
        list.__init__(self, elements)

    def draw(self, painter, font, color, pos_, width):
        pos = Vect(0, 0)
        for element in self:
            painter.move(pos)
            offset = element.draw(painter, font, color, pos_ + pos, width)
            painter.umove(pos)
            pos += offset
        return pos


class Str(Element):

    def __init__(self, value):
        assert not '\n' in value
        self.value = value

    def draw(self, painter, font, color, pos, width):
        if not width:
            return painter.draw_text(self.value, font, color)
        lines = List(self.split(font, pos, width))
        return lines.draw(painter, font, color, pos, None)

    def split(self, font, pos, width):
        # inefficient
        # and hugly
        pos = pos.x

        def eat(text, pos):
            for x in range(2, len(text)+1):
                sub_text = text[:x]
                if font.size(sub_text)[0] >= width - pos:
                    sub_text = sub_text[:-1]
                    x -= 1
                    pos = 0
                    return List([Str(sub_text), NewLine()]), text[x:]
            return Str(text), ""

        ret = []
        text = self.value
        while text:
            element, text = eat(text, pos)
            pos = 0
            ret.append(element)
        return ret


class NewLine(Element):

    def draw(self, painter, font, color, pos, width):
        return Vect(-pos.x, font.get_linesize())


class Cursor(Element):

    def draw(self, painter, font, color, pos, width):
        height = font.get_linesize()
        painter.fill((0, 0, 0), Vect(2, height))
        return Vect(0, 0)


class Text(Element):

    def __init__(self, value):
        assert isinstance(value, basestring)
        self.value = value

    def draw(self, painter, font, color, pos, width):
        lines = self.value.split('\n')
        elements = List()
        for line in lines[:-1]:
            elements.append(Str(line))
            elements.append(NewLine())
        elements.append(Str(lines[-1]))
        return elements.draw(painter, font, color, pos, width)


def draw(painter, text, font, color, width, cursor_pos=None):
    if cursor_pos is not None:
        element = List([Text(text[:cursor_pos]),
                        Cursor(),
                        Text(text[cursor_pos:])])
    else:
        element = Text(text)
    return element.draw(painter, font, color, Vect(0, 0), width) + \
                Vect(0, font.get_linesize() * 2)


def get_size(text, font, width):
    painter = DummyPainter()
    return draw(painter, text, font, None, width)
